/**
 * Description of the accelerometer
 * when the sensor is supplied with 5v, the following output voltages
 * are to be expected::
 *
 * ~ 0.00v  == -250 gS
 * ~ 2.50v  ==    0 gS
 * ~ 5.00v  == +250 gS
 * ~ 0.008V ==    1 gS (the step size)
 *
 * Since the AVR ADC has ten bits of resolution (0-1023),
 * each step for the ADC ~= 0.5 gS
 * 
 * 5v / 1024 == 0.0049 v
 */

/**
 * The configuration variables for this device
 */
const int sensor_pin       = A0;
const int alert_pin        = 13;

/**
 * The hit indication thresholds
 */
const int hit_threshold    = 10;
const int acc_threshold    = 20;
const int trauma_threshold = 95;
const int read_threshold   = 100;

/**
 * The global state variables for this device
 */
int current_read_count   = 0;
int current_hit_count    = 0;
int current_acc_reading  = 0;

/**
 * Setup the hardware on the board
 */
void setup() {
  Serial.begin(9600); 
}

/**
 * Process a new trauma event
 * @param reading The new reading to process
 */ 
void process_trauma(int reading) {
  if (reading > trauma_threshold) {
    Serial.print("id:1,type:trauma,accel:");                       
    Serial.println(reading);
    analogWrite(alert_pin, HIGH);    
  } 
}

/**
 * Process a new reading event
 * @param reading The new reading to process
 */ 
void process_reading(int reading) {
  if (reading > hit_threshold) {
    current_hit_count += 1;
  }
  if (reading > acc_threshold) {
    current_acc_reading += reading;
  }
  if (current_read_count > read_threshold) {
    Serial.print("id:1,type:reading,accel:");                       
    Serial.print(current_acc_reading);
    Serial.print(",hits:");                       
    Serial.println(current_hit_count);

    current_hit_count   = 0;
    current_acc_reading = 0;
    current_read_count  = 0;
    analogWrite(alert_pin, HIGH);    
  } 
}

/**
 * @summary Converts a sensor reading to gS
 * @param reading The reading to convert
 * @return The converted reading
 */
int convert_reading(int reading) {
  reading = (reading >= 512)
    ? reading - 512   // positive acceleration
    : 512 - reading;  // negative acceleration
    
  return reading / 2;
}

/**
 * The main event loop
 */
void loop() {
  current_read_count += 1;
  analogWrite(alert_pin, LOW);    
  int sensor_value = analogRead(sensor_pin);
  int sensor_gs    = convert_reading(sensor_value);
  process_trauma(sensor_gs);
  process_reading(sensor_gs);
  delay(10); // give the adc time to settle  
}
